//! Handshake协议使用示例
//! 
//! 这个示例展示了如何在Swarm中使用zenohlibp2p的handshake协议进行节点认证。

use clap::Parser;
use libp2p::{futures::StreamExt, swarm::SwarmEvent, tcp, noise, yamux, request_response};
use rand::Rng;
use std::{error::Error, time::Duration};
use zenop2p::handshake::{self, HandshakeRequest, HandshakeResponse};

/// Handshake协议使用示例
#[derive(Parser, Debug)]
#[command(version, about, long_about = None)]
struct Args {
    /// 要连接的远程节点地址（可选参数）
    #[arg(short, long)]
    connect: Option<String>,
    
    /// 监听端口（默认随机）
    #[arg(short, long)]
    port: Option<u16>,
    
    /// 要连接的远程节点地址（位置参数）
    connect_addr: Option<String>,
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    // 解析命令行参数
    let args = Args::parse();
    
    // 初始化日志
    tracing_subscriber::fmt::init();

    // 使用SwarmBuilder创建Swarm
    let mut swarm = libp2p::SwarmBuilder::with_new_identity()
        .with_tokio()
        .with_tcp(
            tcp::Config::default(),
            noise::Config::new,
            yamux::Config::default,
        )?
        .with_behaviour(|_| handshake::Behaviour::new())?
        .with_swarm_config(|cfg| cfg.with_idle_connection_timeout(Duration::from_secs(u64::MAX)))
        .build();

    // 设置监听地址
    let listen_addr = if let Some(port) = args.port {
        format!("/ip4/0.0.0.0/tcp/{}", port)
    } else {
        "/ip4/0.0.0.0/tcp/0".to_string()
    };
    
    swarm.listen_on(listen_addr.parse()?)?;

    let peer_id = swarm.local_peer_id().clone();
    println!("启动handshake节点: {}", peer_id);

    println!("节点已启动，等待连接和handshake事件...");

    // 处理连接参数（优先使用位置参数，其次使用--connect参数）
    let connect_addr = args.connect_addr.or(args.connect);
    if let Some(addr) = connect_addr {
        let remote: libp2p::Multiaddr = addr.parse()?;
        swarm.dial(remote)?;
        println!("正在连接: {}", addr);
    }

    // 事件处理循环
    loop {
        match swarm.select_next_some().await {
            // 监听地址事件
            SwarmEvent::NewListenAddr { address, .. } => {
                println!("✅ 监听地址: {}", address);
                
                // 生成完整的连接命令
                let connect_command = format!("cargo run --package handshake-example -- --connect {}/p2p/{}", address, peer_id);
                println!("📎 连接命令: cd {}; {}", std::env::current_dir().unwrap().display(), connect_command);
            }
            
            // 连接建立事件
            SwarmEvent::ConnectionEstablished { peer_id, .. } => {
                println!("🔗 与节点 {} 建立连接", peer_id);
                
                // 发送handshake请求
                let request = HandshakeRequest {
                    peer_id: swarm.local_peer_id().to_string(),
                    credential: vec![1, 2, 3, 4], // 示例凭证
                    timestamp: std::time::SystemTime::now()
                        .duration_since(std::time::UNIX_EPOCH)
                        .unwrap()
                        .as_secs(),
                    nonce: vec![5, 6, 7, 8], // 示例nonce
                };
                
                swarm.behaviour_mut().send_request(peer_id, request);
                println!("📤 向节点 {} 发送handshake请求", peer_id);
            }
            
            // Handshake协议事件
            SwarmEvent::Behaviour(handshake::BehaviourEvent::RequestResponse(
                request_response::Event::Message { message, .. }
            )) => match message {
                request_response::Message::Request { request, channel, .. } => {
                    println!("📥 收到handshake请求");
                    println!("📋 请求内容: peer_id={}, credential={:?}, timestamp={}, nonce={:?}", 
                        request.peer_id, request.credential, request.timestamp, request.nonce);
                    
                    // 临时验证函数：80%成功率，为后续整合node_credential验证做准备
                    fn temporary_credential_validation(_credential: &[u8]) -> bool {
                        let mut rng = rand::thread_rng();
                        rng.gen_bool(0.8) // 80%成功率，用于测试
                    }
                    
                    // 验证请求并生成响应
                    let is_valid = temporary_credential_validation(&request.credential);
                    let response = if is_valid {
                        HandshakeResponse {
                            is_valid: true,
                            message: "Handshake successful".to_string(),
                            error: None,
                            server_timestamp: std::time::SystemTime::now()
                                .duration_since(std::time::UNIX_EPOCH)
                                .unwrap()
                                .as_secs(),
                        }
                    } else {
                        HandshakeResponse {
                            is_valid: false,
                            message: "Credential validation failed".to_string(),
                            error: Some(zenop2p::handshake::HandshakeError::InvalidCredential),
                            server_timestamp: std::time::SystemTime::now()
                                .duration_since(std::time::UNIX_EPOCH)
                                .unwrap()
                                .as_secs(),
                        }
                    };
                    
                    // 发送响应
                    if let Err(e) = swarm.behaviour_mut().send_response(channel, response) {
                        println!("❌ 发送handshake响应失败: {}", e);
                    } else {
                        println!("✅ 发送handshake响应");
                    }
                }
                request_response::Message::Response { request_id, response } => {
                    println!("📥 收到handshake响应 (请求ID: {})", request_id);
                    println!("📋 响应内容: is_valid={}, message={}, error={:?}, server_timestamp={}", 
                        response.is_valid, response.message, response.error, response.server_timestamp);
                    
                    if response.is_valid {
                         println!("✅ handshake成功完成");
                     } else {
                         println!("❌ handshake失败: {}", response.message);
                     }
                 }
             }
             
             // handshake请求失败
             SwarmEvent::Behaviour(handshake::BehaviourEvent::RequestResponse(
                 request_response::Event::OutboundFailure { request_id, error, .. }
             )) => {
                 println!("❌ handshake请求失败 (请求ID: {}): {}", request_id, error);
             }
            
            // 其他事件
            SwarmEvent::ConnectionClosed { peer_id, .. } => {
                println!("🔌 与节点 {} 的连接已关闭", peer_id);
            }
            
            _ => {}
        }
    }
}